<?php

abstract class Service_Base implements Service, ISingleton  
{
	
	public $log_path = '/tmp/';
	/**
	 *
	 * @var Zend_Log
	 */
	private $logger;
	
	/**
	 *
	 * @var Db_Adapter
	 */
	protected $adapter;



	protected $moduleName		= 'default';
	protected $controllerName	= 'index';
	protected $actionName		= 'index';

	/**
	 *
	 * @return array $params
	 */
	protected function getDefaultLinkParams() {
		return array(
			'module'		=> $this->moduleName,
			'controller'	=> $this->controllerName,
			'action'		=> $this->actionName
		);
	}

	/**
	 *
	 * @param array $params
	 * @return string
	 */
	public function getLinkArray(array $params) {
		$params = array_merge($this->getDefaultLinkParams(), $params);

		return StringFunctions::makeUrl($params);
	}

	/**
	 * @return Db_Adapter
	 */
	public function getAdapter() {
		if (!$this->adapter) {
			$this->adapter = Db::getConnection();
		}
		return $this->adapter;
	}

	
	/**
	 * Adding limit constraints from specified Criteria object to select
	 * 
	 * @param Db_Select $select
	 * @param Criteria $criteria
	 * @return Db_Select
	 */
	public static function addLimitConstraint(Db_Select $select, Criteria $criteria)
	{
		$limit = $criteria->getLimit();
		$page = $criteria->getPage();
		if ($limit && $page) {
			$select->limitPage($page, $limit);
		} elseif ($limit) {
			$select->limit($limit);
		}
		return $select;
	}
	
	
	/**
	 * Adding order constraints from specified Criteria object to select
	 * 
	 * @param Db_Select $select
	 * @param Criteria $criteria
	 * @return Db_Select
	 */
	public static function addOrderConstraint(Db_Select $select, Criteria $criteria)
	{
		$order = $criteria->getOrder();
		$orderType = $criteria->getOrderType();
		if ($order) {
			$select->order("$order $orderType");
		}
		return $select;
	}
	
	/**
	 * получить пагинатор
	 * @param Db_Peer $peer
	 * @param Zend_Db_Select $select
	 * @param unknown_type $options
	 */
	public function getPaginatorBySelect(Db_Peer $peer, Zend_Db_Select $select, $options = array()) {
		$page = isset($options['page']) ? (int)$options['page'] : 1;
		$perPage = isset($options['per_page']) ? (int)$options['per_page'] : 10;
		$rangePage = isset($options['range_page']) ? (int)$options['range_page'] : 2;
		
		$adapter = new PaginatorSelectAdapter($select, $peer);
		
		if (isset($options['total_count'])) {
			$adapter->setRowCount((int)$options['total_count']);
		}
		
		$paginator = new Zend_Paginator($adapter);
		
		$paginator->setItemCountPerPage($perPage);
		$paginator->setPageRange($rangePage);
		
		if ($page === 'last') {
			$page = $paginator->count();
		}
		$paginator->setCurrentPageNumber($page);
		
		return $paginator;
	}
	
	
	/**
	 * инициализация логгера
	 * 
	 * @return Zend_Log
	 */
	public function getLogger() {
		//@todo необходимо написать какой-то глобальный логгер
		$needChmod=false;
		if (!$this->logger) {
			$date = date('Y-m-d');
			$format = '[%timestamp%]: %message%' . PHP_EOL;
			$formatter = new Zend_Log_Formatter_Simple($format);
			$dir = BASE_DIR . $this->log_path;
			if (!file_exists($dir)) {
				mkdir($dir);
				chmod($dir, 0777);
			}
			$logFile = $dir . $date . '.log';
			if (!file_exists($logFile)) {
				$needChmod = true;
			}
			$writer = new Zend_Log_Writer_Stream($logFile);
			$writer->setFormatter($formatter);
			$this->logger = new Zend_Log($writer);
			if (file_exists($logFile) && $needChmod) {
				chmod($logFile, 0777);
			}
		}
		
		return $this->logger;
	}
	
	
	public function logFunctionCall($functionName, array $params, $result) {
		$this->getLogger()->info("Function: $functionName");
		$params = implode(' ', $params);
		$this->logger->info("Parameters: $params");
		$resultString = '';
		if (is_array($result)) {
			foreach ($result as $key => $value) {
				$resultString .= "$key => $value; ";
			}
		} else {
			$resultString = $result;
		}
		$this->logger->info('from: '.$_SERVER['REMOTE_ADDR']);
		$this->logger->info("Result: $resultString");
	}
	
	/**
	 * получить текущего пользователя в админке
	 * @return AdminUserRow
	 */
	public static function getAdminUser() {
		Zend_Auth::getInstance()->setStorage(new Zend_Auth_Storage_Session('crud_auth'));
		$login = Zend_Auth::getInstance()->getIdentity();
		$user = null;
		if ($login) {
			$rowset = AdminUserPeer::getInstance()->findByLogin($login);
			if ($rowset) {
				$user = $rowset->current();
			}
		}
		
		return $user;
	}
	
	
	/**
	 * логируем действия пользователя
	 * @param object $changedRow
	 * @param string $message
	 * @param array $changeColumns
	 * @return AdminLogRow
	 */
	public static function logAdminAction(Zend_Db_Table_Row_Abstract $changedRow, $message = '', $changeColumns = array()) {
		$adminUser = self::getAdminUser();
		
		/* @var $tableClass Db_Peer */
		$tableClass = $changedRow->getTableClass();
		if (!is_object($tableClass)) {
			$tableClass = new $tableClass;
		}
		
		$peer = AdminLogPeer::getInstance();
		/* @var $adminLogRow AdminLogRow */
		$adminLogRow = $peer->createRow();
		$adminLogRow->setUserId($adminUser->getId());
		$adminLogRow->setChangedRow($changedRow->getId());
		$adminLogRow->setChangedTable($tableClass->getTableName());
		$adminLogRow->setLog($message);
		if (is_array($changeColumns)) {
			$adminLogRow->setChangedColumns(implode(';', $changeColumns));
		}
		$adminLogRow->save();
		
		return $adminLogRow;
	}
	
	
	
	
	public static function checkIpByNetwork($networks, $ip) {
		// determines if a network in the form of 192.168.17.1/16 or
		// 127.0.0.1/255.255.255.255 or 10.0.0.1 matches a given ip
		if (!is_array($networks)) {
			$networks = array($networks);
		}
		foreach ($networks as $network) {
			$ip_arr = explode('/', $network);
			$network_long = ip2long($ip_arr[0]);
			
			if (!isset($ip_arr[1])) {
				$ip_arr[1] = 32;
			}
			$x = ip2long($ip_arr[1]);
			$mask =  long2ip($x) == $ip_arr[1] ? $x : 0xffffffff << (32 - $ip_arr[1]);
			$ip_long = ip2long($ip);
			
			if (($ip_long & $mask) == ($network_long & $mask)) {
				return true;
			}
		
		}
		return false;
	}
	
	public static function chmod($path, $mode = 02775, $umask = 0) {
		$old = umask($umask);
		chmod($path, $mode);
		umask($old);
	}
	
	public static function makedir($path, $mode = 02775, $umask = 0, $recursion = false) {
		$old = umask($umask);
		$res = mkdir($path, $mode, $recursion);
		umask($old);
		
		return $res;
	}
	
	public static function redirectToTable($table, $sectionRow = null, $save = false) {
		if (!empty($table)) {
			if ($sectionRow) {
				$sectionRow->unLock();
			}
			$redirector = new Zend_Controller_Action_Helper_Redirector();
			$front = Zend_Controller_Front::getInstance();
			$router = $front->getRouter();
			$url = $router->assemble(
				array(
					'action' => 'list', 
					'table' => $table,
					'id' => null,
				)
			);
			if ($save) {
				Db::getConnection()->commit();
			}
			header("Location: $url");
			exit($url);
		}
	}
	
}